<?php

/**
 * NOTICE OF LICENSE
 *
 * THIS SOURCE FILE IS PART OF EVEBIT'S PRIVATE PROJECT.
 * 
 * DO NOT USE THIS FILE IN OTHER PLACE.
 *
 * @docinfo   EveBit_Library.Application Basic components for a web application  
 *
 * @category    EveBit_Library
 * @package     Application
 * @author      Cheng Wei <berlios.o@gmail.com>
 * @version     $$Id: Application.php 419 2011-04-20 02:37:21Z ma.rongliang $$
 * @copyright   Copyright (c) 2008 Evebit Inc. China (http://www.evebit.com)
 */

/** Zend_Application */
require_once 'Zend/Application.php';

/** Core functions */
require_once 'functions.php';

/**
 * Application Runtime Object
 * 
 * You can get instance of session, log, scope, configuration from here.
 * 
 * 1, get current application
 * <code>
 * $app = Evebit_Application::app();
 * </code>
 * 
 * 2, get current scope (front/admin/...)
 * <code>
 * $scope = Evebit_Application::scope();
 * </code>
 * 
 * 3, get current session
 * <code>
 * $session = Evebit_Application::getSession();
 * </code>
 * 
 * 4, get configuration (both from application.ini and database)
 * <code>
 * $path = "default_language";
 * $val = Evebit_Application::config($path);
 * </code>
 * 
 * or
 * 
 * <code>
 * $path = "default_language";
 * $app = Evebit_Application::app();
 * $val = $app->getConfig($path);
 * </code>
 * 
 * 5, write log entry
 * <code>
 * $log = Evebit_Application::app()->getLog();
 * $log->info("these have some message");
 * </code>
 * 
 * 6, get cache
 * <code>
 * $cache = Evebit_Application::app()->getCache();
 * </code>
 * 
 * 7, translate directly
 * 
 * We suppose there are some translations:
 * <code>
 * original string=show this text
 * format string=first arg is %s
 * </code>
 * 
 * then, you can tranlsate as:
 * <code>
 * 
 * Evebit_Application::__('original string');
 * // result is 'show this text'
 * 
 * Evebit_Application::__('format string', '0123');
 * // result is 'first arg is 0123'
 * 
 * Evebit_Application::__(array('format string', '0123'));
 * // result is 'first arg is 0123'
 * 
 * </code>
 * 
 * 
 * @docinfo
 * 
 * @category    EveBit_Library
 * @package     Application
 * @author      Cheng Wei <berlios.o@gmail.com>
 * @version     $$Id: Application.php 419 2011-04-20 02:37:21Z ma.rongliang $$
 */
class Evebit_Application extends Zend_Application {

	/**
	 * @var Evebit_Application
	 */
	protected static $instance = null;

	/**
	 * @var string
	 */
	protected $scope = null;

	/**
	 * @var array
	 */
	protected $_config = null;

	/**
	 * Get current session instance
	 * 
	 * @return Evebit_Application
	 */
	public static function app() {
		return self::$instance;
	}

	/**
	 * Get current scope
	 * 
	 * @return string
	 */
	public static function scope() {
		return self::app()->getScope();
	}

	/**
	 * Get configuration
	 * @param string $path
	 * @return string|array
	 */
	public static function config($path) {
		return self::app()->getConfig($path);
	}

	/**
	 * Get current session instance
	 * 
	 * @return Evebit_Application_Session
	 */
	public static function getSession() {
		if (!Zend_Registry::isRegistered('APPLICATION_SESSION')) {
			$session = new Evebit_Application_Session(self::scope(), true);
			if (!isset($session->messages)) {
				$session->messages = array();
			}
			if (!isset($session->grids)) {
				$session->grids = array();
			}
			Zend_Registry::set('APPLICATION_SESSION', $session);
		}
		return Zend_Registry::get('APPLICATION_SESSION');
	}

	/**
	 * Constructor
	 *
	 * Initialize application. Potentially initializes include_paths, PHP
	 * settings, and bootstrap class.
	 *
	 * @param  string                   $environment
	 * @param  string|array|Zend_Config $options String path to configuration file, or array/Zend_Config of configuration options
	 * @throws Zend_Application_Exception When invalid options are provided
	 * @return void
	 */
	public function __construct($environment, $configPath) {
		$this->_environment = (string) $environment;
		
		if (self::$instance) {
			throw new Zend_Application_Exception('Application just can init one instance');
		}
		
		require_once 'Zend/Loader/Autoloader.php';
		$this->_autoloader = Zend_Loader_Autoloader::getInstance();		
		
		if (null === $configPath || !is_file("$configPath/application.ini")) {
			throw new Zend_Application_Exception(
				'Invalid options provided; must be location of folder which contain config files');
		}
		
		$config = new Zend_Config(array(), true);
		if (is_file("$configPath/default.ini")) {
			$config->merge(new Zend_Config_Ini("$configPath/default.ini", $this->_environment));
		}
		
		$scope = $config->get('options', new Zend_Config(array('scope'=> 'frontend')))->get('scope');
		
		$appConfig = new Zend_Config_Ini("$configPath/application.ini", $scope);
		$config->merge($appConfig);
		
		$this->setOptions($config->toArray());
		
		$this->_config = $config->get('options', new Zend_Config(array('scope'=> 'frontend')))->toArray();
		$this->scope = $this->getConfig('scope');
		
		self::$instance = $this;
	}

	/**
	 * Get current scope
	 * 
	 * @return string
	 */
	public function getScope() {
		return $this->scope;
	}

	/**
	 * Get configuration
	 * 
	 * @param string $key
	 * @return string|array
	 */
	public function getConfig($key) {
		if (isset($this->_config[$key])) {
			return $this->_config[$key];
		} else {
			return null;
		}
	}

	/**
	 * Merge configuration
	 * 
	 * @param array|Zend_Config $config
	 */
	public function mergeConfig($config) {
		if ($config instanceof Zend_Config) {
			$config = $config->toArray();
		}
		if (is_array($config)) {
			$this->_config = array_merge_recursive($this->_config, $config);
		}
	}

	/**
	 * Get log instance
	 * 
	 * @return Zend_Log
	 */
	public function getLog() {
		$bootstrap = $this->getBootstrap();
		if (!$bootstrap->hasPluginResource('log')) {
			return false;
		}
		$log = $bootstrap->bootstrap('log')->getResource('log');
		return $log;
	}

	/**
	 * Get cache instance
	 * 
	 * @param string $name cache configure name
	 * @return Zend_Cache
	 */
	public function getCache($name = null) {
		$bootstrap = $this->getBootstrap();
		if (!$bootstrap->hasPluginResource('cachemanager')) {
			return false;
		}
		/* @var $cacheManager Zend_Cache_Manager */
		$cacheManager = $bootstrap->bootstrap('cachemanager')->getResource('cachemanager');
		if (!$name || !$cacheManager->hasCacheTemplate($name)) {
			$name = 'default';
		}
		return $cacheManager->getCache($name);
	}

	/**
	 * Translate into current locale
	 * 
	 * e.g. 
	 * 
	 * there are to string in language file:
	 * <code>
	 * original string=show this text
	 * format string=first arg is %s
	 * </code>
	 * 
	 * then, you can tranlsate as:
	 * <code>
	 * 
	 * Evebit_Application::__('original string');
	 * // result is 'show this text'
	 * 
	 * Evebit_Application::__('format string', '0123');
	 * // result is 'first arg is 0123'
	 * 
	 * Evebit_Application::__(array('format string', '0123'));
	 * // result is 'first arg is 0123'
	 * 
	 * </code>
	 * 
	 * @see Evebit_Application_Session::translate
	 * 
	 * @param string|array $msg
	 * @return string
	 */
	public static function __($msg) {
		$args = func_get_args();
		return self::getSession()->translate($args);
	}

}